import { useDrag } from 'react-dnd';
import { DragItemType, DropIndicatorType, HolderSvg } from '../utils/constant';
import { useContext, useEffect } from 'react';
import { RuleTreeContext, RuleTreePropsContext } from './RuleTreeContext';
import { getEmptyImage } from 'react-dnd-html5-backend';
import { clsx, wrapperCls } from '../utils';
import styled from 'styled-components';

const Wrapper = styled.div<{
  $isLeaf?: boolean
  $isDragging?: boolean
}>`
  display: inline-flex;
  align-items: center;
  border-radius: 4px;
  padding: ${props => props.$isLeaf ? '6px' : 0};
  opacity: ${props => props.$isDragging ? 0.5 : 1};
  background-color: ${props => props.$isLeaf ? '#fafafa' : 'transparent'};
`;

const WrapperHolder = styled.div`
  display: flex;
  align-items: center;
  cursor: move;
  margin-right: 4px;
`;

export default function DragItem(props: {
  disabled?: boolean
  children: React.ReactNode
  levelPath: number[]
  index: number
  isLeaf?: boolean
  onMove?: (context: {
    dragLevelPath: number[]
    dragIndex: number
    dropLevelPath: number[]
    dropIndex: number
  }) => void
}) {
  const { draggable, uid } = useContext(RuleTreePropsContext);
  const { prefixCls } = useContext(RuleTreeContext);
  const cls = wrapperCls(prefixCls);

  const [{ isDragging }, drag, dragPreview] = useDrag(
    () => ({
      type: DragItemType,
      item: {
        dragLevelPath: props.levelPath,
        dragIndex: props.index,
        dragUid: uid,
      },
      collect: (monitor) => ({
        isDragging: monitor.isDragging(),
      }),
      end: (_, monitor) => {
        const result: any = monitor.getDropResult();
        if (result && result.from === DropIndicatorType) {
          props.onMove?.(result);
        }
      },
      canDrag: !props.disabled,
    }),
    [props.onMove, props.levelPath, props.index, uid, props.disabled],
  );

  const showDraggable = typeof draggable === 'function' ? draggable({ levelPath: props.levelPath }) : draggable !== false;

  useEffect(() => {
    dragPreview(getEmptyImage(), { captureDraggingState: true });
  }, []);

  return (
    <Wrapper
      className={clsx(`${cls}-item-drag`)}
      $isLeaf={props.isLeaf}
      $isDragging={isDragging}
    >
      {
        showDraggable && (
          <WrapperHolder
            ref={drag}
            className={clsx(`${cls}-item-drag-holder`)}
          >{HolderSvg}</WrapperHolder>
        )
      }
      {props.children}
    </Wrapper>
  );
}